﻿using BarTender;
using HttpPrintServer.util.dto;
using Newtonsoft.Json;
using Seagull.BarTender.Print;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using static HttpPrintServer.util.dto.PrintData;

namespace HttpPrintServer
{
    class Program
    {
        // 用于控制服务器运行的标志
        private static bool _isRunning = true;

        static async Task Main(string[] args)
        {
            // 创建 HttpListener 实例
            using (var listener = new HttpListener())
            {
                try
                {
                    string port = ConfigurationManager.AppSettings["port"];
                    // 添加监听的前缀，这里监听本地的 8080 端口
                    listener.Prefixes.Add(port);
                    // 启动监听
                    listener.Start();
                    Console.WriteLine("本地打印服务器已启动，监听地址: " + port);
                    Console.WriteLine("按 'q' 键退出...");

                    // 启动一个任务来处理控制台输入，用于退出程序
                    var consoleTask = Task.Run(() =>
                    {
                        while (_isRunning)
                        {
                            if (Console.ReadKey(true).Key == ConsoleKey.Q)
                            {
                                _isRunning = false;
                                listener.Stop();
                                Console.WriteLine("服务器已停止");
                            }
                        }
                    });

                    // 主循环，处理 HTTP 请求
                    while (_isRunning)
                    {
                        try
                        {
                            // 等待请求并获取上下文
                            var context = await listener.GetContextAsync();
                            // 处理请求
                            await HandleRequestAsync(context);
                        }
                        catch (HttpListenerException ex)
                        {
                            // 当服务器停止时，GetContextAsync 会抛出异常
                            if (ex.ErrorCode != 995) // 995 表示操作被取消
                            {
                                Console.WriteLine($"处理请求时发生错误: {ex.Message}");
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"发生未知错误: {ex.Message}");
                        }
                    }

                    // 等待控制台任务完成
                    await consoleTask;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"启动服务器时发生错误: {ex.Message}");
                }
            }
        }

        // 处理 HTTP 请求的方法
        private static async Task HandleRequestAsync(HttpListenerContext context)
        {
            try
            {
                var request = context.Request;
                var response = context.Response;

                // 设置响应编码
                context.Response.ContentEncoding = Encoding.UTF8;
                context.Response.ContentType = "application/json; charset=utf-8";

                Console.WriteLine($"收到 {request.HttpMethod} 请求: {request.Url}");
                HttpStatusCode statusCode = HttpStatusCode.OK;
                // 设置响应内容
                string responseMessage = "";
                // 默认内容类型
                string contentType = "text/plain";



                // 设置 CORS 响应头 - 关键部分
                response.AddHeader("Access-Control-Allow-Origin", "*"); // 允许所有域名跨域访问
                response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); // 允许的 HTTP 方法
                response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); // 允许的请求头
                response.AddHeader("Access-Control-Max-Age", "86400"); // 预检请求缓存时间（秒）


                // 根据请求路径处理不同的请求
                switch (request.Url.AbsolutePath.ToLower())
                {
                    case "/":
                        responseMessage = "欢迎使用 C# HTTP 服务器!";
                        break;
                    case "/api/info":
                        responseMessage = $"当前时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
                        break;
                    case "/api/data":
                        responseMessage = "{\"name\":\"示例数据\",\"value\":42}";
                        // 设置 JSON 内容类型
                        response.ContentType = "application/json";
                        response.ContentEncoding = Encoding.UTF8;
                        break;
                    case "/api/print":
                        // 处理POST请求中的JSON数据
                        if (request.HttpMethod == "POST" &&
                            request.ContentType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) == true)
                        {
                            // 读取JSON数据
                            using (var reader = new StreamReader(context.Request.InputStream,Encoding.UTF8))
                            {
                                string json = await reader.ReadToEndAsync();
                                Console.WriteLine($"收到JSON数据: {json}");

                                // 解析JSON (这里使用dynamic类型，也可以创建具体的Model类)

                                PrintData printData = JsonConvert.DeserializeObject<PrintData>(json);
                                // 处理数据 - 示例：提取name属性
                                //string name = data?.name;

                                //doPrint1();

                                // doPrint2();

                                if (printData.code != 0|| printData.data.bGoodsList.Count<=0)
                                {
                                    var responseData11 = new { code = 500, msg = "获取打印相关配置失败" };
                                    responseMessage = JsonConvert.SerializeObject(responseData11);
                                    contentType = "application/json";
                                }

                                doPrintMoban(printData);

                                // 返回成功响应
                                //var responseData = new { success = 0, message = "数据接收成功", receivedData = data };

                                var responseData = new { code = 0, msg = "数据接收成功" };
                                responseMessage = JsonConvert.SerializeObject(responseData);
                                contentType = "application/json";
                            }
                        }
                        else
                        {
                            statusCode = HttpStatusCode.BadRequest;
                            var responseData = new { success = 500, message = "无效的请求格式，需要POST方法和application/json内容类型", receivedData = "" };
                            responseMessage = JsonConvert.SerializeObject(responseData);
                        }
                        break;
                    default:
                        // 处理 404 错误
                        response.StatusCode = (int)HttpStatusCode.NotFound;
                        var responseData1 = new { success = 500, message = "未找到请求的资源", receivedData = "" };
                        responseMessage = JsonConvert.SerializeObject(responseData1);
                        break;
                }

                // 设置响应编码 - 修复乱码问题
                response.ContentType = $"{contentType}; charset=utf-8";

                // 设置响应编码
                var buffer = Encoding.UTF8.GetBytes(responseMessage);
                response.ContentLength64 = buffer.Length;

                // 发送响应
                await response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
                response.OutputStream.Close();

                Console.WriteLine($"已响应状态码: {response.StatusCode}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理请求时发生错误: {ex.Message}");
                // 返回 500 错误
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                context.Response.OutputStream.Close();
            }
        }

        //模板打印的
        static  void doPrintMoban(PrintData printData)
        {
            string btw = Environment.CurrentDirectory + printData.data.template.path; // 替换为实际的标签文件路径

            // 使用using语句自动管理引擎资源
            Engine btEngine = new Engine();
            {
                foreach (BGoodsListItem item in printData.data.bGoodsList)
                {
                    btEngine.Start(); // 启动引擎
                    LabelFormatDocument btFormat = btEngine.Documents.Open(btw);
                    btFormat.PrintSetup.PrinterName = ConfigurationManager.AppSettings["PrinterName"];
                    btFormat.PrintSetup.IdenticalCopiesOfLabel = 1; //打印份数
                                                                    // 打印标签或进行其他操作
                                                                    // 检查并替换名为 "Field1" 的数据源字段
                    SetFieldValueIfExists(btFormat, "name", item.name);
                    SetFieldValueIfExists(btFormat, "code", item.code);
                    SetFieldValueIfExists(btFormat, "epc", item.epc);
                    //打印
                    btFormat.Print();

                    btFormat.PrintSetup.Cache.FlushInterval = CacheFlushInterval.PerSession;
                    btFormat.Close(Seagull.BarTender.Print.SaveOptions.DoNotSaveChanges);//不保存对打开模板的修改


                    btEngine.Stop();
                }
                
            }  
        }


        // 辅助方法：安全设置数据源字段值
        static void SetFieldValueIfExists(LabelFormatDocument format, string fieldName, string value)
        {

            SubStrings subStrings= format.SubStrings;
            for (int i = 0; i < subStrings.Count; i++)
            {
                if (subStrings[i].Name == fieldName)
                {
                    format.SubStrings[fieldName].Value = value;
                    Console.WriteLine($"已成功设置字段 '{fieldName}' 的值");
                    break;
                }
            }

            //string subStrings = format.SubStrings.ToString();
            //string[] fields = subStrings.Split(','); // 假设用逗号分隔
            // bool containsField = fields.Contains(fieldName);

            /* if (format.SubStrings is IEnumerable<string> subStringsCollection)
             {
                 bool containsField = subStringsCollection.Contains(fieldName);
                 // 使用 containsField 进行后续处理
                 if (containsField)
                 {
                     format.SubStrings[fieldName].Value = value;
                     Console.WriteLine($"已成功设置字段 '{fieldName}' 的值");
                 }
                 else
                 {
                     Console.WriteLine($"警告: 模板中不存在名为 '{fieldName}' 的数据源字段");
                 }
             }*/


            /* string subStrings = format.SubStrings.ToString();
             string[] fields = subStrings.Split(','); // 假设用逗号分隔
             bool containsField = fields.Contains(fieldName);
             if (containsField)
             {
                 format.SubStrings[fieldName].Value = value;
                 Console.WriteLine($"已成功设置字段 '{fieldName}' 的值");
             }
             else
             {
                 Console.WriteLine($"警告: 模板中不存在名为 '{fieldName}' 的数据源字段");
             }*/

            /* if (format.SubStrings.Contains(fieldName))
             {
                 format.SubStrings[fieldName].Value = value;
                 Console.WriteLine($"已成功设置字段 '{fieldName}' 的值");
             }
             else
             {
                 Console.WriteLine($"警告: 模板中不存在名为 '{fieldName}' 的数据源字段");
             }*/

            // format.SubStrings[fieldName].Value = value;
        }

        private static void doPrint2()
        {
            string printerIp = "192.168.0.104"; // 替换为实际的斑马打印机IP地址
            int printerPort = 9100; // 斑马打印机默认端口
            string templatePath = "E:\\doc\\jw\\联影\\打印模板\\彩盒侧面5226.btw"; // 替换为实际的模板文件路径

            try
            {
                // 从Bartender模板生成ZPL代码（需要先设计好模板）

                string zplCommand = $"^XA^FO50,50^A0N,50,50^FDaaa^FS^XZ";
                /// ^XA^DFXmlExamp.zpl^FS
                /// ^A0N,100,100^FO100,100^FN1"Name"^FS
                /// ^A0N,100,100^FO100,200^FN2"Street"^FS
                /// ^A0N,100,100^FO100,300^FN3"City"^FS
                /// ^A0N,100,100^FO100,400^FN4"State"^FS
                /// ^A0N,100,100^FO100,500^FN5"Zip"^FS
                /// ^XZ

                // 直接通过网络发送ZPL到打印机
                SendZplToPrinter(printerIp, printerPort, zplCommand);

                Console.WriteLine("打印成功");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"打印过程中出现错误：{ex.Message}");
            }
        }
         

        // 通过网络发送ZPL到打印机
        private static void SendZplToPrinter(string printerIp, int printerPort, string zplContent)
        {
            using (var client = new TcpClient())
            {
                client.Connect(printerIp, printerPort);

                using (var stream = client.GetStream())
                using (var writer = new StreamWriter(stream, Encoding.ASCII))
                {
                    writer.Write(zplContent);
                    writer.Flush();
                }
            }
        }


        /// <summary>
        /// 打印的方法,发送指令到打印机
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private static void doPrint1()
        {
            Console.WriteLine("打印的方法,发送指令到打印机");

            string printerName = "ZDesigner ZT411R-300dpi ZPL网络"; // 替换为实际的斑马打印机名称
            string templatePath = "E:\\doc\\jw\\联影\\打印模板\\彩盒侧面5226.btw"; // 替换为实际的模板文件路径

            // 创建Bartender应用程序对象
            var btApp = new Application();

            try
            {
                // 打开模板文件
                var btFormat = btApp.Formats.Open(templatePath, false, printerName);

                // 设置打印参数，如打印份数等
                btFormat.PrintSetup.IdenticalCopiesOfLabel = 1;

                // 设置变量值（如果有）
                var data = new Dictionary<string, string>
            {
                {"ProductName", "iPhone 15"},
                {"Price", "5999"},
                {"Quantity", "1"}
            };

                foreach (var item in data)
                {
                    btFormat.SetNamedSubStringValue(item.Key, item.Value);
                }

                // 打印标签
                int result = btFormat.PrintOut(true, false);

                // 检查打印结果
                if (result != 0)
                {
                    Console.WriteLine($"打印错误，错误代码：{result}");
                }
                else
                {
                    Console.WriteLine("打印成功");
                }

                // 关闭模板
                btFormat.Close(BtSaveOptions.btDoNotSaveChanges);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"打印过程中出现错误：{ex.Message}");
            }
            finally
            {
                // 退出Bartender应用程序
                btApp.Quit(BtSaveOptions.btDoNotSaveChanges);
            }

        }
    }
}
